/*
 * Cria dinamicamente um Menu/SubMenu usando o perfil do usuario
 * Um menu dinamico é criado setando "overlay=true" do p:menu
 * Pode-se Chamar este Bean usando: 
 *        <p:menu overlay=true model="#{menuBean.model}"/>
 * 
 * Se caso precise passagem de parametros alterar esta classe para atender
 * esta necessidade. Algo tal como:
 *      <p:menuitem value="Menu 01" action="#{myController.search}">
 *          <f:setPropertyActionListener target="#{managedBean.myparam}" value="1" />
 *      </p:menuitem>
 *      
 *      private int myParam;
 *      public int getMyParam() {
 *          return myParam;
 *      }
 *      public void setMyParam(int myParam) {
 *         this.myParam = myParam;
 *      }
 *      public void search() {
 *          //Aqui uso o parametro enviado pela view
 *          service.find(myParam);
 *      }
 */
package br.com.lm.view;

import br.com.lm.base.eao.EaoException;
import br.com.lm.entity.CtrlModulo;
import br.com.lm.entity.CtrlPerfil;
import br.com.lm.entity.CtrlPerfilAcesso;
import br.com.lm.entity.CtrlUsuario;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.faces.application.FacesMessage;
import javax.faces.context.FacesContext;
import javax.servlet.http.HttpSession;
import org.primefaces.component.menuitem.MenuItem;
import org.primefaces.component.submenu.Submenu;
import org.primefaces.model.DefaultMenuModel;
import org.primefaces.model.MenuModel;

public class CtrlMenuDynamicBean {

    private FacesContext ctx = FacesContext.getCurrentInstance();
    private MenuModel model = new DefaultMenuModel();

    private CtrlUsuario usuarioAutenticado;    
  //private Map<CtrlPerfilAcessoPK, List<CtrlObjetoAcesso>> mapModuloObjAcesso;
    
    private HttpSession session;
    
    /*
     * Cria Menu Dinamicamente
     */
    public CtrlMenuDynamicBean() {        
        session = (HttpSession) ctx.getExternalContext().getSession(false);
        try {
            usuarioAutenticado = (CtrlUsuario)session.getAttribute("usuarioAutenticado");
          //Objeto de Autorizacao nao usado neste contexto  
          //mapModuloObjAcesso = (Map<CtrlPerfilAcessoPK,List<CtrlObjetoAcesso>>)session.getAttribute("mapModuloObjAcesso");
            if (checkPerfilAcesso())
                criaMenuAcesso();
        } catch (Exception ex) {
            Logger.getLogger(CtrlMenuDynamicBean.class.getName()).log(Level.SEVERE, null, ex);
            addMessage("Login Expirado... Entre novamente no sistema LM!");
            try {
                ctx.getExternalContext().redirect(ctx.getExternalContext().getRequestContextPath() + "/login.jsf");
            } catch (IOException ex1) {
                Logger.getLogger(CtrlMenuDynamicBean.class.getName()).log(Level.SEVERE, null, ex1);
            }
        }
    }

    /*
     * Retorna o Menu Dinamico
     */
    public MenuModel getModel() {
        return model;
    }
    
    /*
     * Home page
     */
    private void home() throws IOException {
        ctx = FacesContext.getCurrentInstance();
        ctx.getExternalContext().redirect(ctx.getExternalContext().getRequestContextPath() + "/home.jsf");
    }

    /*
     * Mensagens do sistema
     */
    private void addMessage(String summary) {
        FacesMessage message = new FacesMessage(FacesMessage.SEVERITY_INFO, summary, null);
        FacesContext.getCurrentInstance().addMessage(null, message);
    }

    /*
     * Verifica perfil do usuario
     */
    private boolean checkPerfilAcesso() {       
        boolean lReturn = false; 
        StringBuilder sb = new StringBuilder();
        
        //Verifica o status do perfil do usuário
        CtrlPerfil perfil = usuarioAutenticado.getIdPerfil();
        Character stsPefil = perfil.getStsPerfil() == null || perfil.getStsPerfil().equals(Character.valueOf('\u0000')) 
                             ? 'L' : perfil.getStsPerfil();
        if (stsPefil.equals('B')) {
            sb.append("Perfil[");
            sb.append(perfil.getDscPerfil());
            sb.append("] bloqueado! Contactar Administrador do sistema LM.");
            addMessage(sb.toString());
        }
        else 
        if (stsPefil.equals('D')) {
            sb.append("Perfil[");
            sb.append(perfil.getDscPerfil());
            sb.append("] desativado! Contactar Administrador do sistema LM.");
            addMessage(sb.toString());
        }
        else
        lReturn = true;
        
        return lReturn;
    }   
    
    /*
     * Cria Menu/submenu dinamicamente usando o perfil de acesso do usuario
     */
    @SuppressWarnings({"UnusedAssignment","MismatchedQueryAndUpdateOfCollection"})
    private void criaMenuAcesso() throws EaoException {
        StringBuilder sb = new StringBuilder();
        List<String> msgsErro = new ArrayList<String>();
        
        //Busca hierarquia do menu de acesso
        Collection<CtrlPerfilAcesso> ctrlAcesso = usuarioAutenticado.getIdPerfil().getCtrlPerfilAcessoCollection();
        if (ctrlAcesso == null || ctrlAcesso.isEmpty()) 
            return;
        
        //Cria Menu de Acesso dinamicamente
        Submenu  subMenuPaiRoot = null;
        Submenu  subMenuRoot    = null;
        MenuItem menuItem       = null;
            
        Map<Integer, Submenu> mapModuloRoot = new HashMap<Integer, Submenu>(ctrlAcesso.size());
                
        CtrlModulo moduloRoot = null;
        CtrlModulo moduloItem = null;
            
        while (ctrlAcesso.iterator().hasNext()) {                
            CtrlPerfilAcesso ctrlPerfilAcesso = ctrlAcesso.iterator().next();
                
            moduloRoot = ctrlPerfilAcesso.getCtrlModuloRoot();
            moduloItem = ctrlPerfilAcesso.getCtrlModuloItem();
            
            //Controle de Menu Root
            if (moduloRoot != null) {
                if (moduloRoot.getAplModulo() != null && !moduloRoot.getAplModulo().trim().equals("")) {
                    sb.setLength(0);
                    sb.append("Módulo [");
                    sb.append(moduloRoot.getDscModulo());
                    sb.append("] Erro de sistema, modulo root não pode estar associado a uma aplicação!");
                    msgsErro.add(sb.toString());    
                    continue;
                 }
                
                 //Cria o SubMenu de Root
                 subMenuRoot = new Submenu();
                 subMenuRoot.setLabel(moduloRoot.getDscModulo());
                 if (moduloRoot.getMenuitemIcon() != null && !moduloRoot.getMenuitemIcon().trim().equals(""))
                    subMenuRoot.setIcon(moduloRoot.getMenuitemIcon());
                 model.addSubmenu(subMenuRoot);  
                        
                 //Verifica se o SubMenu de Root esta abaixo de outro subMenu de Root
                 if (mapModuloRoot.containsKey(moduloRoot.getPredModulo())) {
                     subMenuPaiRoot = mapModuloRoot.get(moduloRoot.getPredModulo());
                     subMenuPaiRoot.getChildren().add(subMenuRoot);
                     //Atualiza SubMenu de Root como Pai do SubMenu de Root atual
                     mapModuloRoot.put(moduloRoot.getPredModulo(), subMenuPaiRoot);
                 }
                 
                 //Adiciona o SubMenu de Root no controle logico 
                 mapModuloRoot.put(moduloRoot.getIdModulo(), subMenuRoot);
                 continue;
            }  
                
            //Controle de Menu de Item
            if (moduloItem != null) {
                if (moduloItem.getAplModulo() == null || moduloItem.getAplModulo().trim().equals("")) {
                    sb.setLength(0);
                    sb.append("Módulo [");
                    sb.append(moduloItem.getDscModulo());
                    sb.append("] Erro de sistema, modulo item sem aplicação para navegação!");
                    msgsErro.add(sb.toString());    
                    continue;
                }
                
                //Cria um Menu de Item
                menuItem =  new MenuItem();                
                menuItem.setValue(moduloItem.getDscModulo());
                
                if (moduloItem.getAplModuloType().equals('1'))
                  menuItem.setUrl(moduloItem.getAplModulo());     //("#")
                else
                  menuItem.setOutcome(moduloItem.getAplModulo()); //("/")
                
                if (moduloItem.getMenuitemActionlistener() != null && !moduloItem.getMenuitemActionlistener().trim().equals("")) {
                    //menuItem.setActionListener("");
                }
                if (moduloItem.getMenuitemUpdate() != null && !moduloItem.getMenuitemUpdate().trim().equals(""))
                    menuItem.setUpdate(moduloItem.getMenuitemUpdate());
                if (moduloItem.getMenuitemIcon() != null && !moduloItem.getMenuitemIcon().trim().equals(""))
                    menuItem.setIcon(moduloItem.getMenuitemIcon());
                if (moduloItem.getMenuitemOnclick() != null && !moduloItem.getMenuitemOnclick().trim().equals(""))
                    menuItem.setOnclick(moduloItem.getMenuitemOnclick());
                menuItem.setAjax(moduloItem.getMenuitemAjax());
                
                //Procura o SubMenu de Root se existir 
                if (mapModuloRoot.containsKey(moduloItem.getPredModulo())) {
                    subMenuRoot = mapModuloRoot.get(moduloItem.getPredModulo());
                    subMenuRoot.getChildren().add(menuItem);
                    mapModuloRoot.put(moduloItem.getPredModulo(), subMenuRoot);
                }
                else {
                    //Menuitem órfã
                    model.addMenuItem(menuItem);
                 }                
             }
        } 
        
        //Se houve erro no sistema, reporta as ocorrencias
        for (String msgErro: msgsErro) {
            addMessage(msgErro);
        }
    }   
     
}
